/* file contenente la definizione delle funzioni della classe ixp_graph che si occupano di stampare 
	il contenuto dei membri della classe (debug) o stampare le metriche su file */
#include "ixp_graph.h"


void ixp_graph:: stampa_proprieta_ixp ()
{
	map <pair <int, int>, metriche_ixp>::iterator it;
	ofstream f(file_met_ixp);
			
	for(it=proprieta_ixp.begin(); it!=proprieta_ixp.end(); it++){
		f<<"IXP ID:"<<(*it).first.first<<endl;
		switch ( (*it).first.second ) {
			case 0:
				f<<"\t(grafo ottenuto considerando tutti i membri come AS normali)"<<endl;
				break;
			case 1:
				f<<"\t(grafo ottenuto non considerando il route server fra i membri)"<<endl;
				break;
			case 2:
				f<<"\t(grafo ottenuto considerando una clique fra i membri connessi al RS)"<<endl;
				break;
			default:
				f<<"\t(valore che indica il tipo di grafo non corretto)"<<endl;
		}
		f<<"\tTotal Member: "<<(*it).second.tot_members<<endl;
		f<<"\tPublic Member: "<<(*it).second.public_members<<endl;
		f<<"\tPeering Member: "<<(*it).second.peering_members<<endl;
		f<<"\tPeering: "<<(*it).second.peering<<endl;
		f<<"\tEdges Cut: "<<(*it).second.edges_cut<<endl;
		f<<"\tAvg Degree: "<<fixed<<setprecision(2)<<(*it).second.avg_degree<<endl;
		f<<"\tMax Degree: "<<(*it).second.max_degree.first<<"\t< ";
		set < unsigned int >::const_iterator it2 = (*it).second.max_degree.second.begin();
		for (; it2 != (*it).second.max_degree.second.end(); it2++ )
			f<<"AS"<<(*it2)<<" ";
		f<<">"<<endl;
		f<<"\tHub Dominance: "<<(*it).second.hub_dominance<<endl;
		f<<"\tVolume: "<<(*it).second.volume<<endl;
		f<<"\tAvg Clustering Coefficient: "<<(*it).second.avg_clustering<<endl;
		f<<"\tLink Density: "<<(*it).second.link_density<<endl;
		f<<"\tScaled Link Density: "<<(*it).second.scaled_link_density<<endl;
		f<<"\tInternal Density: "<<(*it).second.internal_density<<endl;
		f<<"\tAvg Shortest Path Lenght: "<<setprecision(4)<<(*it).second.avg_shortest_path_length<<endl;
		f<<"\tDiameter: "<<(*it).second.diameter<<endl;
		f<<"\tOut Degree Fraction: "<<setprecision(4)<<(*it).second.odf<<endl;
		f<<"\tNode ODF: ";
		map < unsigned int, float >::const_iterator it4 = (*it).second.node_odf.begin();
		for (; it4 != (*it).second.node_odf.end(); it4++ )
			f<<"(AS"<<(*it4).first<<","<<(*it4).second<<") ";
		f<<endl;
		f<<"\tMin ODF: "<<setprecision(4)<<(*it).second.min_odf<<endl;
		f<<"\tMax ODF: "<<setprecision(4)<<(*it).second.max_odf<<endl;
		f<<"\tAvg ODF: "<<setprecision(4)<<(*it).second.avg_odf<<endl;
		f<<"\tFlake ODF: "<<setprecision(2)<<(*it).second.flake_odf<<endl;
		f<<"\tNode Embeddedness: ";
		f<<setprecision(4);
		map < unsigned int, float >::const_iterator it5 = (*it).second.node_embed.begin();
		for (; it5 != (*it).second.node_embed.end(); it5++ )
			f<<"(AS"<<(*it5).first<<","<<(*it5).second<<") ";
		f<<endl;
		f<<"\tMin Embeddedness: "<<setprecision(4)<<(*it).second.min_embed<<endl;
		f<<"\tMax Embeddedness: "<<setprecision(4)<<(*it).second.max_embed<<endl;
		f<<"\tAvg Embeddedness: "<<setprecision(4)<<(*it).second.avg_embed<<endl;
		f<<"\tConductance: "<<(*it).second.conductance<<endl;
		f<<"\tExpansion: "<<setprecision(2)<<(*it).second.expansion<<endl;
		f<<"\tAvg Shell Index: "<<(*it).second.avg_shell_index<<endl;
		f<<"\tMax Shell Index: "<<(*it).second.max_shell_index<<endl;
		f<<"\tMin Shell Index: "<<(*it).second.min_shell_index<<endl;
		f<<"\tShell Index Probability Mass Function: ";
		map < unsigned int, float >::const_iterator it3 = (*it).second.shell_index_pmf.begin();
		for (; it3 != (*it).second.shell_index_pmf.end(); it3++ )
			f<<"("<<(*it3).first<<","<<(*it3).second<<") ";
		f<<endl;
		f<<"\tShell Index CCDF: ";
		map < unsigned int, float >::const_iterator it6 = (*it).second.shell_index_ccdf.begin();
		for (; it6 != (*it).second.shell_index_ccdf.end(); it6++ )
			f<<"("<<(*it6).first<<","<<(*it6).second<<") ";
		f<<endl;
		f<<"\tCut Ratio: "<<setprecision(4)<<(*it).second.cut_ratio<<endl;
		f<<"\tNormalized Cut: "<<setprecision(2)<<(*it).second.norm_cut<<endl;
		f<<endl;
	}
	f.close();
}


//By Giovanni Lelli
void ixp_graph::stampa_metriche_asn()
{
	map <pair <unsigned int, int>, metriche_as >::iterator it;
	ofstream f(file_met_asn);
	unsigned int asn;
	int graphs_type;
	for(it=as_metric.begin(); it!=as_metric.end();it++){
		asn = it->first.first;
		graphs_type = it->first.second;
		pair < unsigned int, int > as_metric_key ( asn, graphs_type );
		
		f<<"ASN: "<<asn<<endl;
		switch ( graphs_type ) {
			case 0:
				f<<"\t(considerati i sottografi con tutti i membri come AS normali)"<<endl;
				break;
			case 1:
				f<<"\t(considerati i sottografi togliendo il RS)"<<endl;
				break;
			case 2:
				f<<"\t(considerati i sottografi costruendo una clique fra i peer del RS)"<<endl;
				break;
			default:
				f<<"\t(valore che indica il tipo di grafo non corretto)"<<endl;
		}
		f<<"\t"<<"Member Presence = "<<as_metric[as_metric_key].member_presence<<endl;
		f<<"\t"<<"Member Connectivity = "<<as_metric[as_metric_key].member_connectivity<<endl;
		f<<"\t"<<"Global Degree = "<<as_metric[as_metric_key].global_degree<<endl;
	}
	f.close();
}


void ixp_graph:: stampa_proprieta_aggregate ()
{
	map < pair < string, int>, metriche_agg>::iterator it;
	ofstream f(file_met_agg);
			
	for(it=proprieta_ixp_agg.begin(); it!=proprieta_ixp_agg.end(); it++){
		f<<"CONTINENTE:"<<it->first.first<<endl;
		switch ( it->first.second ) {
			case 0:
				f<<"\t(considerati i sottografi fatti con tutti i membri come AS normali)"<<endl;
				break;
			case 1:
				f<<"\t(considerati i sottografi fatti togliendo il route server)"<<endl;
				break;
			case 2:
				f<<"\t(considerati i sottografi fatti creando una clique fra gli AS peer del RS)"<<endl;
				break;
			default:
				f<<"\t(valore che indica il tipo di grafo non corretto)"<<endl;
		}
		f<<"\tNumero IXP: "<<it->second.num_ixp<<endl;
		f<<"\tTotal Member: "<<fixed<<setprecision(2)<<it->second.tot_members<<endl;
		f<<"\tPublic Member: "<<it->second.public_members<<endl;
		f<<"\tPeering Member: "<<it->second.peering_members<<endl;
		f<<"\tPeering: "<<it->second.peering<<endl;
		f<<"\tEdges Cut: "<<it->second.edges_cut<<endl;
		f<<"\tAvg Degree: "<<it->second.avg_degree<<endl;
		f<<"\tMax Degree: "<<it->second.max_degree.first<<"\t< ";
		map < unsigned int, unsigned int >::const_iterator it2 = it->second.max_degree.second.begin();
		for (; it2 != it->second.max_degree.second.end(); it2++ )
			f<<"(AS"<<it2->first<<", "<<it2->second<<") ";
		f<<">"<<endl;
		f<<"\tHub Dominance: "<<it->second.hub_dominance.first<<endl;
		f<<"\tVolume: "<<it->second.volume<<endl;
		f<<"\tAvg Clustering Coefficient: "<<it->second.avg_clustering.first<<endl;
		f<<"\tLink Density: "<<it->second.link_density.first<<endl;
		f<<"\tLink Density Probability Mass Function: ";
		map < float, float >::const_iterator it_ld = it->second.link_density_pmf.begin();
		for(; it_ld != it->second.link_density_pmf.end(); it_ld++ )
			f<<"("<<it_ld->first<<","<<it_ld->second<<") ";
		f<<endl;
		f<<"\tLink Density CCDF: ";
		it_ld = it->second.link_density_ccdf.begin();
		for(; it_ld != it->second.link_density_ccdf.end(); it_ld++ )
			f<<"("<<it_ld->first<<","<<it_ld->second<<") ";
		f<<endl;
		f<<"\tScaled Link Density: "<<it->second.scaled_link_density.first<<endl;
		f<<"\tInternal Density: "<<it->second.internal_density.first<<endl;
		f<<"\tAvg Shortest Path Lenght: "<<it->second.avg_shortest_path_length.first<<endl;
		f<<"\tDiameter: "<<it->second.diameter.first<<endl;
		f<<"\tOut Degree Fraction: "<<it->second.odf.first<<endl;
		f<<"\tMin ODF: "<<it->second.min_odf.first<<endl;
		f<<"\tMax ODF: "<<it->second.max_odf.first<<endl;
		f<<"\tAvg ODF: "<<it->second.avg_odf.first<<endl;
		f<<"\tFlake ODF: "<<it->second.flake_odf.first<<endl;
		f<<"\tMin Embeddedness: "<<it->second.min_embed.first<<endl;
		f<<"\tMax Embeddedness: "<<it->second.max_embed.first<<endl;
		f<<"\tAvg Embeddedness: "<<it->second.avg_embed.first<<endl;
		f<<"\tConductance: "<<it->second.conductance.first<<endl;
		f<<"\tExpansion: "<<it->second.expansion<<endl;
		f<<"\tAvg Shell Index: "<<it->second.avg_shell_index<<endl;
		f<<"\tMax Shell Index: "<<it->second.max_shell_index<<endl;
		f<<"\tMin Shell Index: "<<it->second.min_shell_index<<endl;
		f<<"\tShell Index Probability Mass Function: ";
		map < unsigned int, float >::const_iterator it3 = it->second.shell_index_pmf.begin();
		for (; it3 != it->second.shell_index_pmf.end(); it3++ )
			f<<"("<<it3->first<<","<<it3->second<<") ";
		f<<endl;
		f<<"\tShell Index CCDF: ";
		map < unsigned int, float >::const_iterator it4 = it->second.shell_index_ccdf.begin();
		for (; it4 != it->second.shell_index_ccdf.end(); it4++ )
			f<<"("<<it4->first<<","<<it4->second<<") ";
		f<<endl;
		f<<"\tCut Ratio: "<<setprecision(4)<<it->second.cut_ratio.first<<endl;
		f<<"\tNormalized Cut: "<<setprecision(2)<<it->second.norm_cut.first<<endl;
		f<<endl;
	}
	f.close();
}

    
//by Giacomo Tanganelli
void ixp_graph::stampa_link_indotti()
{
	map <int, set <pair <unsigned int,unsigned int> > >::iterator it_ixp;
    	set <pair <unsigned int,unsigned int> >::iterator it_ASN;
    	for(it_ixp=link_indotti.begin(); it_ixp!=link_indotti.end(); it_ixp++)
    	{
    		cout<<"IXP_ID"<<(*it_ixp).first<<endl;
    		
    		for(it_ASN=((*it_ixp).second).begin(); it_ASN!=((*it_ixp).second).end(); it_ASN++)
    		{
    			cout<<(*it_ASN).first<<"-"<<(*it_ASN).second<<endl;
    		}
    	}
    	cout<<"Press any key and then enter to continue..."<<endl;
	char c;
	cin>>c;
}


//By Giovanni Lelli
void ixp_graph::stampa_nodi_indotti()
{
	cout<<"STAMPA NODI INDOTTI"<<endl;
	map <int,map <unsigned int,unsigned int> >::iterator it;
	map <unsigned int,unsigned int>::iterator it_as;
	for ( it=nodi_indotti.begin() ; it!=nodi_indotti.end(); it++ ){
		cout<<"ixp_id: "<<(*it).first<<endl;
		for (it_as=((*it).second).begin(); it_as!=((*it).second).end(); it_as++)
		cout<<(*it_as).first<<" => " << (*it_as).second<<endl;
	}
    cout<<"Press any key and then enter to continue..."<<endl;
    char s;    
    cin>>s;
}


// by Alessio Casella
void ixp_graph:: stampa_AS_speciali ( int i )
{
	const char* msg = ( i == 0 ) ? "AS esclusi:" : "AS privati:";
	set <pair <unsigned int, unsigned int> > & var = ( i == 0 ) ? AS_esclusi : AS_privati;
	stampa_set_di_pair_uint_uint( msg, var );
}


// by Alessio Casella
void ixp_graph:: stampa_set_di_pair_uint_uint ( const char* msg, 
												const set < pair < unsigned int, unsigned int > >& var )
{
	cout<<msg<<endl;
	set <pair <unsigned int, unsigned int> >::const_iterator it;
	for ( it = var.begin(); it != var.end(); it++ )
		cout<<"\t"<<it->first<<" - "<<it->second<<endl;
	cout<<"Press any key and then enter to continue..."<<endl;
	char c;
	cin>>c;
}


//by Alessandro Iaria
void ixp_graph::debug_membri_ixp()
{
    char i;
    cout<< "Debug per membri_ixp"<<endl;
    cout<<"Press any key and then enter to continue..."<<endl;
    cin>>i;
    for (map <int, set<unsigned int> >::iterator itr= membri_ixp.begin(); itr!=membri_ixp.end(); itr++)
    {
        cout<< "Membri di "<<(*itr).first<<":"<<endl;
        for (set<unsigned int>::iterator itr2=(*itr).second.begin(); itr2!= (*itr).second.end(); itr2++)
            cout<< "\t"<<(*itr2)<<endl;
        cout<<"FINE "<<(*itr).first<<endl;
    }
    cout<<"DEBUG FINITO"<<endl;
    cout<<"Press any key and then enter to continue..."<<endl;
    cin>>i;
}


//by Giovanni Lelli 
void ixp_graph::debug_route_server()   
{
    map <int,unsigned int>::iterator it;
    for(it=route_server.begin();it!=route_server.end();it++)
    {
         cout<<"IXP_id: "<<(*it).first;
         cout<<"\t RS: "<<route_server[(*it).first]<<endl;
    }
}


//by Giovanni    
 void ixp_graph::valutazione_ixp()
 {  
    int num_ixp= nodi_indotti.size();
    cout<<endl<<"IXP osservati= "<< num_ixp<<endl; //campione di riferimento per lo studio
    int members=0;
    int peer=0;
    int diametro=0;
    int count=0;
    int count2=0;
    int count3=0;
    int count4=0;
    
    const int percent = 120;
    const int percent_eu = 500;
    /* ixp con un numero di membri pubblici pari almeno al percent% del numero medio di membri pubblici 
    	degli ixp del continente (percent_eu% per gli ixp europei):
    	key = continente,
    	value = insieme di triplette ixp_id - ixp_short_name - numero_membri_pubblici
    */
    map < string, set < pair < int, pair < string, unsigned int > > > > ixp_grandi;
    int count5=0;
    int ixp_id;
    float avg_member;
    
    map <pair <int, int>, metriche_ixp>::iterator it;
    for(it=proprieta_ixp.begin();it!=proprieta_ixp.end();it++){
           if((*it).first.second==0){
                members+=(*it).second.public_members;
                if((*it).second.public_members<10)count++;
                if((*it).second.public_members<100)count2++;
                if((*it).second.public_members>300)count3++;
                
                ixp_id = (*it).first.first;
			    pair < string, int > cont ( ixps[ixp_id].continent, 0 );
                avg_member = proprieta_ixp_agg[cont].public_members;
                if((ixps[ixp_id].continent!="EU"&&(*it).second.public_members>(float)percent/100*avg_member)||
                	(ixps[ixp_id].continent=="EU"&&(*it).second.public_members>(float)percent_eu/100*avg_member)) {
                	count5++;
                	pair < string, unsigned int > interna ( ixps[ixp_id].short_name, (*it).second.public_members );
				    pair < int, pair < string, unsigned int > > esterna ( ixp_id, interna );
                	ixp_grandi[ixps[ixp_id].continent].insert( esterna );
                }
                
                peer+=(*it).second.peering;
                if((*it).second.diameter!=0){
                /* non considero nella media gli ixp che hanno diametro 0 
                	(hanno tutti i nodi sconnessi) */
                	diametro+=(*it).second.diameter;
                	count4++;
                }
            }
     }
     float avg_members=(float)members/ (float)num_ixp;   //dimensione media ixp
     cout<<"Numero medio di membri pubblici= "<<avg_members<<endl;
     cout<<"Gli IXP che hanno meno di 10 membri pubblici sono: "<<count<< " ossia il "<<(float)(count*100)/(float)num_ixp<<" %"<<endl;
     cout<<"Gli IXP che hanno meno di 100 membri pubblici sono: "<<count2<<" ossia il "<<(float)(count2*100)/(float)num_ixp<<" %"<<endl;
     cout<<"Gli IXP che hanno più di 300 membri pubblici sono: "<<count3<<" ossia il "<<(float)(count3*100)/(float)num_ixp<<" %"<<endl;
     
     cout<<"Gli IXP con un numero di membri pubblici pari almeno al "<<percent<<"% della media del continente ";
     cout<<"("<<percent_eu<<"% per gli IXP europei) sono: "<<count5;
     cout<<" ossia il "<<(float)(count5*100)/(float)num_ixp<<" %"<<endl;
     cout<<"\te sono (divisi per continente):"<<endl;
     map < string, set < pair < int, pair < string, unsigned int > > > >::const_iterator it2;
     set < pair < int, pair < string, unsigned int > > >::const_iterator it3;
     for ( it2 = ixp_grandi.begin(); it2 != ixp_grandi.end(); it2++ ) {
	     cout<<"\t\t"<<it2->first<<endl;
	     cout<<"\t\t   [ ixp_id,\tnum_membri,\t(ixp_name) ]:"<<endl;
	     for ( it3 = it2->second.begin(); it3 != it2->second.end(); it3++ )
	     	cout<<"\t\t\t"<<it3->first<<"\t"<<it3->second.second<<"\t\t("<<it3->second.first<<")"<<endl;
	 }
	 
     float avg_peering=(float)peer/(float)num_ixp;
     float full_mesh=(avg_members*(avg_members-1))/2;
     cout<<"Numero medio di peering= "<<avg_peering<<" ossia il "<<(avg_peering*100)/full_mesh<<" %"<<" di una full mesh media"<<endl;  //si da un'ulteriore indicazione sulle      dimensioni generali degli ixp
     float avg_diametro=(float)diametro/(float)count4;
     cout<<"Diametro medio= "<<avg_diametro<<endl; //si dimostra la small world property
     cout<<endl;
     
} 

//by Giovanni Lelli
void ixp_graph::check_metrics()
{
    map <pair <int, int>, metriche_ixp>::iterator it;
    for(it=proprieta_ixp.begin();it!=proprieta_ixp.end();it++)
    {
        metriche_ixp met=(*it).second;
        if(met.public_members>met.tot_members) cout<<"IXP_ID: "<<(*it).first.first<<" = errore conteggio membri pubblici"<<endl;
        if(met.peering_members>met.public_members) cout<<"IXP_ID:"<<(*it).first.first<<" = errore conteggio peering_member"<<endl;
        if(met.peering>(met.public_members*(met.public_members-1))/2) cout<<"IXP_ID:"<<(*it).first.first<<" = errore conteggio peering"<<endl;
        if(met.max_degree.first>(met.public_members-1)) cout<<"IXP_ID:"<<(*it).first.first<<" = errore max_degree"<<endl;
        if(met.hub_dominance<0 || met.hub_dominance>1) cout<<"IXP_ID:"<<(*it).first.first<<" = errore hub_dominance"<<endl;
        if(met.volume!=met.peering*2) cout<<"IXP_ID:"<<(*it).first.first<<" = errore volume"<<endl;
        if(met.avg_clustering<0 || met.avg_clustering>1) cout<<"IXP_ID:"<<(*it).first.first<<" = errore avg_clustering coeffincient"<<endl;
        if(met.odf<0 || met.odf>1) cout<<"IXP_ID:"<<(*it).first.first<<" = errore odf"<<endl;
        if(met.conductance<0 || met.conductance>1) cout<<"IXP_ID:"<<(*it).first.first<<" = errore conductance"<<endl;
        if(met.min_odf<0 || met.min_odf>1) cout<<"IXP_ID:"<<(*it).first.first<<" = errore min_odf"<<endl;
        if(met.max_odf<0 || met.max_odf>1) cout<<"IXP_ID:"<<(*it).first.first<<" = errore max_odf"<<endl;
        if(met.avg_odf<0 || met.avg_odf>1) cout<<"IXP_ID:"<<(*it).first.first<<" = errore avg_odf"<<endl;
        map < unsigned int, float >::iterator n;
        for(n=met.node_odf.begin();n!=met.node_odf.end();n++)
             if((*n).second<0 || (*n).second>1) cout<<"IXP_ID:"<<(*it).first.first<<" = errore node_odf di ASN "<<(*n).first<<endl;
        if(met.flake_odf<0 || met.flake_odf>1) cout<<"IXP_ID:"<<(*it).first.first<<" = errore flake_odf"<<endl;   
        if(met.cut_ratio<0 || met.cut_ratio>1) cout<<"IXP_ID:"<<(*it).first.first<<" = errore cut_ratio"<<endl;    
        if(met.max_shell_index > met.max_degree.first) cout<<"IXP_ID:"<<(*it).first.first<<" = errore max_shell_index"<<endl;
        map < unsigned int, float >::iterator sh;
        float distr=0;
        for(sh=met.shell_index_pmf.begin();sh!=met.shell_index_pmf.end();sh++)  distr+=(*sh).second;
        distr = floor(distr+0.5);
        if(distr!=1) cout<<"IXP_ID:"<<(*it).first.first<<" = errore shell_index_pmf: "<<distr<<endl;
        if(met.min_embed<0 || met.min_embed>1) cout<<"IXP_ID:"<<(*it).first.first<<" = errore min_embed"<<endl;
        if(met.max_embed<0 || met.max_embed>1) cout<<"IXP_ID:"<<(*it).first.first<<" = errore max_embed"<<endl;
        if(met.avg_embed<0 || met.avg_embed>1) cout<<"IXP_ID:"<<(*it).first.first<<" = errore avg_embed"<<endl;
        map < unsigned int, float >::iterator e;
        for(e=met.node_embed.begin();e!=met.node_embed.end();e++)
             if((*e).second<0 || (*e).second>1) cout<<"IXP_ID:"<<(*it).first.first<<" = errore node_embed di ASN "<<(*e).first<<endl;
    }
}


//by Giacomo Tanganelli
void ixp_graph:: stampa_proprieta_ixp_gnuplot (int id_ixp[], int num_ixp, int type_graph)
{
    const char* f_txt;
    if (num_ixp!=0)
        f_txt=gnuplot_custom;
    else
    {	    
        switch (type_graph)
	    {
	    case 0:
	        f_txt=gnuplot_0;
	        break;
	    case 1:
	        f_txt=gnuplot_1;
	        break;
	    case 2:
	        f_txt=gnuplot_2;
	        break;
	    default:
	        return;
	    }
	}
	ofstream f(f_txt);
	f<<"#Metriche IXP: type_graph: "<<type_graph<<"."<<endl;
	f<<"#IXP_ID 1\tTotal Member 2\tPublic Member 3\tPeering Member 4\tPeering 5\tEdges Cut 6\tAvg Degree 7\tMax Degree 8";
	f<<"\tHub Dominance 9\tVolume 10\tAvg Clustering Coefficient 11\tLink Density 12\tScaled Link Density 13\tInternal Density 14";
	f<<"\tAvg Shortest Path 15\tDiameter 16\tOut Degree Fraction 17\tMin ODF 18\tMax ODF 19\tAvg ODF 20\tFlake ODF 21";
	f<<"\tConductance 22\tExpansion 23\tAvg Shell Index 24\tMax Shell Index 25\tMin Shell Index 26\tCut Ratio 27\tNormalized Cut 28";
	f<<"\tNome IXP 29"<<endl;
	for(int i=0;i<num_ixp;i++)
	{	
		pair <int, int> ixp (id_ixp[i],type_graph);		
		f<<setw(8) <<id_ixp[i]<<setw(1)<<"\t";
		f<<setw(14)<<proprieta_ixp[ixp].tot_members<<setw(1)<<"\t";
		f<<setw(15) <<proprieta_ixp[ixp].public_members<<setw(1)<<"\t";
		f<<setw(16) <<proprieta_ixp[ixp].peering_members<<setw(1)<<"\t";
		f<<setw(9) <<proprieta_ixp[ixp].peering<<setw(1)<<"\t";
		f<<setw(11) <<proprieta_ixp[ixp].edges_cut<<setw(1)<<"\t";
		f<<setw(12) <<fixed<<setprecision(2)<<proprieta_ixp[ixp].avg_degree<<setw(1)<<"\t";
		f<<setw(12) <<proprieta_ixp[ixp].max_degree.first<<setw(1)<<"\t";
		f<<setw(15) <<proprieta_ixp[ixp].hub_dominance<<setw(1)<<"\t";
		f<<setw(9) <<proprieta_ixp[ixp].volume<<setw(1)<<"\t";
		f<<setw(29) <<proprieta_ixp[ixp].avg_clustering<<setw(1)<<"\t";
		f<<setw(15) <<proprieta_ixp[ixp].link_density<<setw(1)<<"\t";
		f<<setw(22) <<proprieta_ixp[ixp].scaled_link_density<<setw(1)<<"\t";
		f<<setw(19) <<proprieta_ixp[ixp].internal_density<<setw(1)<<"\t";
		f<<setw(20) <<setprecision(4)<<proprieta_ixp[ixp].avg_shortest_path_length<<setw(1)<<"\t";
		f<<setw(11) <<proprieta_ixp[ixp].diameter<<setw(1)<<"\t";
		f<<setw(22) <<setprecision(4)<<proprieta_ixp[ixp].odf<<setw(1)<<"\t";
		f<<setw(10) <<setprecision(4)<<proprieta_ixp[ixp].min_odf<<setw(1)<<"\t";
		f<<setw(10) <<setprecision(4)<<proprieta_ixp[ixp].max_odf<<setw(1)<<"\t";
		f<<setw(10) <<setprecision(4)<<proprieta_ixp[ixp].avg_odf<<setw(1)<<"\t";
		f<<setw(12) <<setprecision(2)<<proprieta_ixp[ixp].flake_odf<<setw(1)<<"\t";
		f<<setw(14) <<proprieta_ixp[ixp].conductance<<setw(1)<<"\t";
		f<<setw(12) <<setprecision(2)<<proprieta_ixp[ixp].expansion<<setw(1)<<"\t";
		f<<setw(18) <<proprieta_ixp[ixp].avg_shell_index<<setw(1)<<"\t";
		f<<setw(18) <<proprieta_ixp[ixp].max_shell_index<<setw(1)<<"\t";
		f<<setw(18) <<proprieta_ixp[ixp].min_shell_index<<setw(1)<<"\t";
		f<<setw(12) <<setprecision(4)<<proprieta_ixp[ixp].cut_ratio<<setw(1)<<"\t";
		f<<setw(17) <<setprecision(2)<<proprieta_ixp[ixp].norm_cut<<setw(1)<<"\t";
		f<<setw(11) <<ixps[ixp.first].short_name<<endl;
    }
	if (num_ixp == 0)
	    for (map <pair <int, int>, metriche_ixp>:: iterator ixp= proprieta_ixp.begin(); ixp!=proprieta_ixp.end(); ixp++)
	        if (ixp->first.second == type_graph)
	        {
	            f<<setw(8) <<ixp->first.first<<setw(1)<<"\t";
		        f<<setw(14) <<ixp->second.tot_members<<setw(1)<<"\t";
		        f<<setw(15) <<ixp->second.public_members<<setw(1)<<"\t";
		        f<<setw(16) <<ixp->second.peering_members<<setw(1)<<"\t";
		        f<<setw(9) <<ixp->second.peering<<setw(1)<<"\t";
		        f<<setw(11) <<ixp->second.edges_cut<<setw(1)<<"\t";
		        f<<setw(12) <<fixed<<setprecision(2)<<ixp->second.avg_degree<<setw(1)<<"\t";
		        f<<setw(12) <<ixp->second.max_degree.first<<setw(1)<<"\t";
		        f<<setw(15) <<ixp->second.hub_dominance<<setw(1)<<"\t";
		        f<<setw(9) <<ixp->second.volume<<setw(1)<<"\t";
		        f<<setw(29) <<ixp->second.avg_clustering<<setw(1)<<"\t";
		        f<<setw(15) <<ixp->second.link_density<<setw(1)<<"\t";
		        f<<setw(22) <<ixp->second.scaled_link_density<<setw(1)<<"\t";
		        f<<setw(19) <<ixp->second.internal_density<<setw(1)<<"\t";
		        f<<setw(20) <<setprecision(4)<<ixp->second.avg_shortest_path_length<<setw(1)<<"\t";
		        f<<setw(11) <<ixp->second.diameter<<setw(1)<<"\t";
		        f<<setw(22) <<setprecision(4)<<ixp->second.odf<<setw(1)<<"\t";
		        f<<setw(10) <<setprecision(4)<<ixp->second.min_odf<<setw(1)<<"\t";
		        f<<setw(10) <<setprecision(4)<<ixp->second.max_odf<<setw(1)<<"\t";
		        f<<setw(10) <<setprecision(4)<<ixp->second.avg_odf<<setw(1)<<"\t";
		        f<<setw(12) <<setprecision(2)<<ixp->second.flake_odf<<setw(1)<<"\t";
		        f<<setw(14) <<ixp->second.conductance<<setw(1)<<"\t";
		        f<<setw(12) <<setprecision(2)<<ixp->second.expansion<<setw(1)<<"\t";
		        f<<setw(18) <<ixp->second.avg_shell_index<<setw(1)<<"\t";
		        f<<setw(18) <<ixp->second.max_shell_index<<setw(1)<<"\t";
		        f<<setw(18) <<ixp->second.min_shell_index<<setw(1)<<"\t";
		        f<<setw(12) <<setprecision(4)<<ixp->second.cut_ratio<<setw(1)<<"\t";
		        f<<setw(17) <<setprecision(2)<<ixp->second.norm_cut<<setw(1)<<"\t";
		        f<<setw(11) <<ixps[ixp->first.first].short_name<<endl;
		    }
	f.close();
}


//by Alessio Casella
void ixp_graph:: stampa_prop_ixp_agg_gnuplot ( int type_graph, const char* file_out )
{
	ofstream f(file_out);
	
	f<<"# metriche aggregate per continente ";
	switch ( type_graph ) {
			case 0:
				f<<"(considerati i sottografi fatti con tutti i membri come AS normali)"<<endl;
				break;
			case 1:
				f<<"(considerati i sottografi fatti togliendo il route server)"<<endl;
				break;
			case 2:
				f<<"(considerati i sottografi fatti creando una clique fra gli AS peer del RS)"<<endl;
				break;
			default:
				f<<"(valore che indica il tipo di grafo non corretto)"<<endl;
		}
	
	const int len = 32;
	const char* field[len] = { "CONTINENTE", "Numero IXP", "Total Member", "Public Member", 
								"Peering Member", "Peering", "Edges Cut", "Avg Degree", "Max Degree", 
								"Hub Dominance", "Volume", "Avg Clustering Coefficient", "Link Density", 
								"Scaled Link Density", "Internal Density", "Avg Shortest Path", 
								"Diameter", "Out Degree Fraction", "Min ODF", "Max ODF", "Avg ODF", 
								"Flake ODF", "Min Embeddedness", "Max Embeddedness", "Avg Embeddedness", 
								"Conductance", "Expansion", "Avg Shell Index", "Max Shell Index", 
								"Min Shell Index", "Cut Ratio", "Normalized Cut" };
	
	f<<"# ";
	for ( int i = 0; i < len; i++ )
		f<<i+1<<") "<<field[i]<<"\t";
	f<<endl;
	
	map < pair < string, int >, metriche_agg >::const_iterator it;
	for ( it = proprieta_ixp_agg.begin(); it != proprieta_ixp_agg.end(); it++ )
		if ( it->first.second == type_graph ) {
			f<<it->first.first;
			f<<"\t"<<it->second.num_ixp;
			f<<"\t"<<fixed<<setprecision(2)<<it->second.tot_members;
			f<<"\t"<<it->second.public_members;
			f<<"\t"<<it->second.peering_members;
			f<<"\t"<<it->second.peering;
			f<<"\t"<<it->second.edges_cut;
			f<<"\t"<<it->second.avg_degree;
			f<<"\t"<<it->second.max_degree.first;
			f<<"\t"<<it->second.hub_dominance.first;
			f<<"\t"<<it->second.volume;
			f<<"\t"<<it->second.avg_clustering.first;
			f<<"\t"<<it->second.link_density.first;
			f<<"\t"<<it->second.scaled_link_density.first;
			f<<"\t"<<it->second.internal_density.first;
			f<<"\t"<<it->second.avg_shortest_path_length.first;
			f<<"\t"<<it->second.diameter.first;
			f<<"\t"<<it->second.odf.first;
			f<<"\t"<<it->second.min_odf.first;
			f<<"\t"<<it->second.max_odf.first;
			f<<"\t"<<it->second.avg_odf.first;
			f<<"\t"<<it->second.flake_odf.first;
			f<<"\t"<<it->second.min_embed.first;
			f<<"\t"<<it->second.max_embed.first;
			f<<"\t"<<it->second.avg_embed.first;
			f<<"\t"<<it->second.conductance.first;
			f<<"\t"<<it->second.expansion;
			f<<"\t"<<it->second.avg_shell_index;
			f<<"\t"<<it->second.max_shell_index;
			f<<"\t"<<it->second.min_shell_index;
			f<<"\t"<<setprecision(4)<<it->second.cut_ratio.first;
			f<<"\t"<<setprecision(2)<<it->second.norm_cut.first;
			f<<endl;
		}
		
	f.close();
}

/*
//by Alessio Casella
void ixp_graph:: stampa_proprieta_as_gnuplot ( int type_graph, const char* file_out )
{
	ofstream f(file_out);
	
	f<<"# metriche degli Autonomous System ";
	switch ( type_graph ) {
			case 0:
				f<<"(considerati i sottografi fatti con tutti i membri come AS normali)"<<endl;
				break;
			case 1:
				f<<"(considerati i sottografi fatti togliendo il route server)"<<endl;
				break;
			case 2:
				f<<"(considerati i sottografi fatti creando una clique fra gli AS peer del RS)"<<endl;
				break;
			default:
				f<<"(valore che indica il tipo di grafo non corretto)"<<endl;
		}
	
	const int len = 4;
	const char* field[len] = { "ASN", "Member Presence", "Member Connectivity", "Global Degree" };
	
	f<<"# ";
	for ( int i = 0; i < len; i++ )
		f<<i+1<<") "<<field[i]<<"\t";
	f<<endl;
	
	map < pair < unsigned int, int >, metriche_as >::const_iterator it;
	for ( it = as_metric.begin(); it != as_metric.end(); it++ )
		if ( it->first.second == type_graph ) {
			f<<it->first.first;
			f<<"\t"<<it->second.member_presence;
			f<<"\t"<<it->second.member_connectivity;
			f<<"\t"<<it->second.global_degree;
			f<<endl;
		}
		
	f.close();
}
*/

//By Giovanni Lelli
void ixp_graph::ordina_members_gnuplot(int type_graph, const char* file_out){
    
     ofstream f(file_out);
     list<int> metrica_ordinata;
     map <pair <int, int>, metriche_ixp>::iterator it;
     for (it=proprieta_ixp.begin();it!=proprieta_ixp.end();it++){
        if ( it->first.second == type_graph ) 
        metrica_ordinata.push_back((*it).second.public_members);
      }
      metrica_ordinata.sort();
      list<int>::iterator l=metrica_ordinata.end();
      l--;
      for(;l!=metrica_ordinata.begin();l--){ 
        f<<(*l)<<endl;
       }
       f<<(*l)<<endl;    
}

void ixp_graph:: stampa_degree_ccdf ( int ixp_id, int type_graph, const char* file_out )
{
	string path ( file_out );
	path += '_';
	char id_str[10];
	sprintf( id_str, "%d", ixp_id );
	path += id_str;
	path += '_';
	char tg_str[1];
	sprintf( tg_str, "%d", type_graph );
	path += tg_str;
	path += ".txt";
	
	ofstream f( path.c_str() );
	
	f<<"# CCDF del degree dell'IXP "<<ixp_id<<endl;
	switch ( type_graph ) {
		case 0:
			f<<"# (considerati i sottografi fatti con tutti i membri come AS normali)"<<endl;
			break;
		case 1:
			f<<"# (considerati i sottografi fatti togliendo il route server)"<<endl;
			break;
		case 2:
			f<<"# (considerati i sottografi fatti creando una clique fra gli AS peer del RS)"<<endl;
			break;
		default:
			f<<"# (valore che indica il tipo di grafo non corretto)"<<endl;
	}
	
	const int len = 2;
	const char* field[len] = { "valore", "probabilita'" };
	
	f<<"# ";
	for ( int i = 0; i < len; i++ )
		f<<i+1<<") "<<field[i]<<"\t";
	f<<endl;
	
	map < unsigned int, float >::const_iterator it;
	pair < int, int > key ( ixp_id, type_graph );
	map < pair < int, int >, metriche_ixp >::const_iterator prop = proprieta_ixp.find( key );
	if ( prop == proprieta_ixp.end() )
		f<<"# NESSUNA METRICA ASSOCIATA ALLA COPPIA IXP-TIPO GRAFO SPECIFICATA!"<<endl;
	else {
		const map < unsigned int, float >* dgccdf = &(prop->second.degree_ccdf);
		for ( it = dgccdf->begin(); it != dgccdf->end(); it++ ) {
			f<<it->first<<'\t';
			f<<fixed<<setprecision(4)<<it->second<<endl;
		}
	}
		
	f.close();

}
//by Giacomo Tanganelli
void ixp_graph::stampa_as_tear1_gnuplot(int ixp_id, const char* file_out){
	
	string path (file_out);
	path += '_';
	char num[4];
	sprintf (num, "%d", ixp_id);
	path += num;
	
	int type_graph=0;
	pair <int, int> ixp (ixp_id, type_graph);

	set <unsigned int> ASN_max_degree=proprieta_ixp[ixp].max_degree.second;
	set <unsigned int>::iterator max;
	set <pair <unsigned int,unsigned int> >::iterator it;
	
	
	int i=0;
	for(max=ASN_max_degree.begin();max!=ASN_max_degree.end();max++)
	{
		i++;
		path += '_';
		char num2[2];
		sprintf (num2, "%d", i);
		path += num2;
		path += ".txt";
		
		ofstream f(path.c_str());
		f<<"# AS supposti di Tear 1 ";
		switch ( type_graph ) {
				case 0:
					f<<"(considerati i sottografi fatti con tutti i membri come AS normali)"<<endl;
					break;
				case 1:
					f<<"(considerati i sottografi fatti togliendo il route server)"<<endl;
					break;
				case 2:
					f<<"(considerati i sottografi fatti creando una clique fra gli AS peer del RS)"<<endl;
					break;
				default:
					f<<"(valore che indica il tipo di grafo non corretto)"<<endl;
			}
		f<<"# Il primo valore e' il global degree dell'AS con massimo degree"<<endl;
		pair <unsigned int, int> ASN_MAX ((*max), type_graph);
		f<<"#"<<(*max)<<"\t"<<as_metric[ASN_MAX].global_degree<<endl;
		
		int tot = 0;
		int customer = 0;
		for(it=link_indotti[ixp_id].begin(); it!=link_indotti[ixp_id].end(); it++)
		{
			if((*it).first==(*max))
			{
				pair<unsigned int, int> ASN ((*it).second, type_graph);
				f<<(*it).second<<"\t"<<as_metric[ASN].global_degree<<"\t"<<as_metric[ASN_MAX].global_degree<<endl;
				tot++;
				if ( as_metric[ASN].global_degree == 1 )
					customer++;
			}
			if((*it).second==(*max))
			{
				pair<unsigned int, int> ASN ((*it).first, type_graph);
				f<<(*it).first<<"\t"<<as_metric[ASN].global_degree<<"\t"<<as_metric[ASN_MAX].global_degree<<endl;
				tot++;
				if ( as_metric[ASN].global_degree == 1 )
					customer++;
			}
		
		}
		float percent_customer = ( (float)customer / (float)tot ) * 100;
		f<<"# percentuale di customer: "<<fixed<<setprecision(2)<<percent_customer<<"%"<<endl;
		f.close();
	}
	
}


//by Alessio Casella
/*void ixp_graph:: stampa_shell_index_pmf ( string continent, int type_graph, const char* file_out )
{
	string path ( file_out );
	path += '_';
	path += continent;
	path += '_';
	char tg_str[1];
	sprintf( tg_str, "%d", type_graph );
	path += tg_str;
	path += ".txt";
	
	ofstream f( path.c_str() );
	
	f<<"# probability mass function dello shell index degli IXP del continente "<<continent<<endl;
	switch ( type_graph ) {
		case 0:
			f<<"# (considerati i sottografi fatti con tutti i membri come AS normali)"<<endl;
			break;
		case 1:
			f<<"# (considerati i sottografi fatti togliendo il route server)"<<endl;
			break;
		case 2:
			f<<"# (considerati i sottografi fatti creando una clique fra gli AS peer del RS)"<<endl;
			break;
		default:
			f<<"# (valore che indica il tipo di grafo non corretto)"<<endl;
	}
	
	const int len = 2;
	const char* field[len] = { "valore", "probabilita'" };
	
	f<<"# ";
	for ( int i = 0; i < len; i++ )
		f<<i+1<<") "<<field[i]<<"\t";
	f<<endl;
	
	map < unsigned int, float >::const_iterator it;
	pair < string, int > key ( continent, type_graph );
	map < pair < string, int >, metriche_agg >::const_iterator prop = proprieta_ixp_agg.find( key );
	if ( prop == proprieta_ixp_agg.end() )
		f<<"# NESSUNA METRICA ASSOCIATA ALLA COPPIA CONTINENTE-TIPO GRAFO SPECIFICATA!"<<endl;
	else {
		const map < unsigned int, float >* sipmf = &(prop->second.shell_index_pmf);
		for ( it = sipmf->begin(); it != sipmf->end(); it++ ) {
			f<<it->first<<'\t';
			f<<fixed<<setprecision(4)<<it->second<<endl;
		}
	}
		
	f.close();
}
*/

//by Alessio Casella
void ixp_graph:: stampa_shell_index_ccdf ( string continent, int type_graph, const char* file_out )
{
	string path ( file_out );
	path += '_';
	path += continent;
	path += '_';
	char tg_str[1];
	sprintf( tg_str, "%d", type_graph );
	path += tg_str;
	path += ".txt";
	
	ofstream f( path.c_str() );
	
	f<<"# CCDF dello shell index degli IXP del continente "<<continent<<endl;
	switch ( type_graph ) {
		case 0:
			f<<"# (considerati i sottografi fatti con tutti i membri come AS normali)"<<endl;
			break;
		case 1:
			f<<"# (considerati i sottografi fatti togliendo il route server)"<<endl;
			break;
		case 2:
			f<<"# (considerati i sottografi fatti creando una clique fra gli AS peer del RS)"<<endl;
			break;
		default:
			f<<"# (valore che indica il tipo di grafo non corretto)"<<endl;
	}
	
	const int len = 2;
	const char* field[len] = { "valore", "probabilita'" };
	
	f<<"# ";
	for ( int i = 0; i < len; i++ )
		f<<i+1<<") "<<field[i]<<"\t";
	f<<endl;
	
	map < unsigned int, float >::const_iterator it;
	pair < string, int > key ( continent, type_graph );
	map < pair < string, int >, metriche_agg >::const_iterator prop = proprieta_ixp_agg.find( key );
	if ( prop == proprieta_ixp_agg.end() )
		f<<"# NESSUNA METRICA ASSOCIATA ALLA COPPIA CONTINENTE-TIPO GRAFO SPECIFICATA!"<<endl;
	else {
		const map < unsigned int, float >* siccdf = &(prop->second.shell_index_ccdf);
		for ( it = siccdf->begin(); it != siccdf->end(); it++ ) {
			f<<it->first<<'\t';
			f<<fixed<<setprecision(4)<<it->second<<endl;
		}
	}
		
	f.close();
}


//by Alessio Casella
void ixp_graph:: stampa_link_density_ccdf ( string continent, int type_graph, const char* file_out )
{
	string path ( file_out );
	path += '_';
	path += continent;
	path += '_';
	char tg_str[1];
	sprintf( tg_str, "%d", type_graph );
	path += tg_str;
	path += ".txt";
	
	ofstream f( path.c_str() );
	
	f<<"# CCDF della link density degli IXP del continente "<<continent<<endl;
	switch ( type_graph ) {
		case 0:
			f<<"# (considerati i sottografi fatti con tutti i membri come AS normali)"<<endl;
			break;
		case 1:
			f<<"# (considerati i sottografi fatti togliendo il route server)"<<endl;
			break;
		case 2:
			f<<"# (considerati i sottografi fatti creando una clique fra gli AS peer del RS)"<<endl;
			break;
		default:
			f<<"# (valore che indica il tipo di grafo non corretto)"<<endl;
	}
	
	const int len = 2;
	const char* field[len] = { "valore", "probabilita'" };
	
	f<<"# ";
	for ( int i = 0; i < len; i++ )
		f<<i+1<<") "<<field[i]<<"\t";
	f<<endl;
	
	map < float, float >::const_iterator it;
	pair < string, int > key ( continent, type_graph );
	map < pair < string, int >, metriche_agg >::const_iterator prop = proprieta_ixp_agg.find( key );
	if ( prop == proprieta_ixp_agg.end() )
		f<<"# NESSUNA METRICA ASSOCIATA ALLA COPPIA CONTINENTE-TIPO GRAFO SPECIFICATA!"<<endl;
	else {
		const map < float, float >* ldccdf = &(prop->second.link_density_ccdf);
		for ( it = ldccdf->begin(); it != ldccdf->end(); it++ ) {
			f<<fixed<<setprecision(2)<<it->first<<'\t';
			f<<fixed<<setprecision(4)<<it->second<<endl;
		}
	}
		
	f.close();
}


//by Alessio Casella
void ixp_graph:: stampa_shell_index_ccdf ( int ixp_id, int type_graph, const char* file_out )
{
	string path ( file_out );
	path += '_';
	char id_str[10];
	sprintf( id_str, "%d", ixp_id );
	path += id_str;
	path += '_';
	char tg_str[1];
	sprintf( tg_str, "%d", type_graph );
	path += tg_str;
	path += ".txt";
	
	ofstream f( path.c_str() );
	
	f<<"# CCDF dello shell index dell'IXP "<<ixp_id<<endl;
	switch ( type_graph ) {
		case 0:
			f<<"# (considerati i sottografi fatti con tutti i membri come AS normali)"<<endl;
			break;
		case 1:
			f<<"# (considerati i sottografi fatti togliendo il route server)"<<endl;
			break;
		case 2:
			f<<"# (considerati i sottografi fatti creando una clique fra gli AS peer del RS)"<<endl;
			break;
		default:
			f<<"# (valore che indica il tipo di grafo non corretto)"<<endl;
	}
	
	const int len = 2;
	const char* field[len] = { "valore", "probabilita'" };
	
	f<<"# ";
	for ( int i = 0; i < len; i++ )
		f<<i+1<<") "<<field[i]<<"\t";
	f<<endl;
	
	map < unsigned int, float >::const_iterator it;
	pair < int, int > key ( ixp_id, type_graph );
	map < pair < int, int >, metriche_ixp >::const_iterator prop = proprieta_ixp.find( key );
	if ( prop == proprieta_ixp.end() )
		f<<"# NESSUNA METRICA ASSOCIATA ALLA COPPIA IXP-TIPO GRAFO SPECIFICATA!"<<endl;
	else {
		const map < unsigned int, float >* siccdf = &(prop->second.shell_index_ccdf);
		for ( it = siccdf->begin(); it != siccdf->end(); it++ ) {
			f<<it->first<<'\t';
			f<<fixed<<setprecision(4)<<it->second<<endl;
		}
	}
		
	f.close();
}


//by Alessandro Iaria
/*void ixp_graph:: stampa_shind_pmf(int ixp_id, int type_graph)
{
	string file=shind_base;
	char num[10]="";
	sprintf(num, "%d", ixp_id);
	file+="_";
	file+=num;
	sprintf(num, "%d", type_graph);
	file+="_";
	file+=num;
	ofstream f(file.c_str());
	f<<"#Frazione di AS per valore di Shell Index equivalente."<<endl;
	f<<setw(10)<<"#<Sh.Ind.>\t<% AS>"<<endl;
	pair<int, int> ixp (ixp_id, type_graph);
	map <pair<int, int>, metriche_ixp> ::iterator itr=proprieta_ixp.find(ixp);
	if(itr==proprieta_ixp.end())
	{
		f<<"ERRORE: "<<ixp_id<<" di tipo "<<type_graph<<" non esiste."<<endl;
		return;
	}
	for (map<unsigned int, float>::iterator itr2=itr->second.shell_index_pmf.begin(); 
						itr2!=itr->second.shell_index_pmf.end(); itr2++)
		f<<(*itr2).first<<'\t'<<fixed<<setprecision(2)<<(*itr2).second<<endl;
}
*/

//By Giovanni Lelli
void ixp_graph::ordina_peering_gnuplot(int type_graph, const char* file_out){

     ofstream f(file_out);
     list<int> metrica_ordinata;
     map <pair <int, int>, metriche_ixp>::iterator it;
     for (it=proprieta_ixp.begin();it!=proprieta_ixp.end();it++){
        if ( it->first.second == type_graph ) 
        metrica_ordinata.push_back((*it).second.peering);
      }
      metrica_ordinata.sort();
      list<int>::iterator l=metrica_ordinata.end();
      l--;
      for(;l!=metrica_ordinata.begin();l--){ 
        f<<(*l)<<endl;
       }
       f<<(*l)<<endl;    
}


//by Giovanni Lelli
void ixp_graph::ordina_as_members_gnuplot(const char* file_out){
         ofstream f(file_out);
         list<pair<int, unsigned int > > metrica_ordinata;
         map <pair <unsigned int, int>, metriche_as > ::iterator it;
         for (it=as_metric.begin();it!=as_metric.end();it++){
        if ( it->first.second == 0) 
        metrica_ordinata.push_back(pair<int, unsigned int>((*it).second.member_presence,(*it).first.first));
      }
      metrica_ordinata.sort();
      list <pair<int, unsigned int > >::iterator l=metrica_ordinata.end();
      l--;
      for(;l!=metrica_ordinata.begin();l--){ 
        f<<(*l).first<<"\t"<< (*l).second<<endl;
       }
       f<<(*l).first<<"\t" <<(*l).second<<endl;;    
}


//by Giovanni Lelli
void ixp_graph::ordina_as_connectivity_gnuplot(const char* file_out){
         ofstream f(file_out);
          list<pair<int, unsigned int > > metrica_ordinata;
         map <pair <unsigned int, int>, metriche_as > ::iterator it;
         for (it=as_metric.begin();it!=as_metric.end();it++){
        if ( it->first.second == 0) 
     metrica_ordinata.push_back(pair<int, unsigned int>((*it).second.member_connectivity,(*it).first.first));
      }
      metrica_ordinata.sort();
      list <pair<int, unsigned int > >::iterator l=metrica_ordinata.end();
      l--;
      for(;l!=metrica_ordinata.begin();l--){ 
       f<<(*l).first<<"\t"<< (*l).second<<endl;
       }
       f<<(*l).first<<"\t" <<(*l).second<<endl;;     
}

void ixp_graph:: stampa_globaldg_ccdf ( int ixp_id, int type_graph, const char* file_out )
{
	string path ( file_out );
	path += '_';
	char id_str[10];
	sprintf( id_str, "%d", ixp_id );
	path += id_str;
	path += '_';
	char tg_str[1];
	sprintf( tg_str, "%d", type_graph );
	path += tg_str;
	path += ".txt";
	
	ofstream f( path.c_str() );
	
	f<<"# CCDF del global_degree dell'IXP "<<ixp_id<<endl;
	switch ( type_graph ) {
		case 0:
			f<<"# (considerati i sottografi fatti con tutti i membri come AS normali)"<<endl;
			break;
		case 1:
			f<<"# (considerati i sottografi fatti togliendo il route server)"<<endl;
			break;
		case 2:
			f<<"# (considerati i sottografi fatti creando una clique fra gli AS peer del RS)"<<endl;
			break;
		default:
			f<<"# (valore che indica il tipo di grafo non corretto)"<<endl;
	}
	
	const int len = 2;
	const char* field[len] = { "valore", "probabilita'" };
	
	f<<"# ";
	for ( int i = 0; i < len; i++ )
		f<<i+1<<") "<<field[i]<<"\t";
	f<<endl;
    
    map< unsigned int, float> globaldg;
    map <unsigned int, unsigned int>::iterator as;
    for (as=nodi_indotti[ixp_id].begin();as!=nodi_indotti[ixp_id].end();as++){
        pair < int, int > chiave ( (*as).first, type_graph );
        unsigned int key=as_metric[chiave].global_degree;
        if( globaldg.find(key)!=globaldg.end())
        globaldg[key]+= (float)1/(float) nodi_indotti[ixp_id].size();
        else
        globaldg[key]= (float)1/(float) nodi_indotti[ixp_id].size();
        }
     map <unsigned int, float> ccdf;
     pmf_to_ccdf<unsigned int>(&globaldg,ccdf);      
     map< unsigned int, float>::iterator it;
     for(it=ccdf.begin();it!=ccdf.end();it++){
            f<<it->first<<'\t';
		    f<<fixed<<setprecision(4)<<it->second<<endl;
		}
	
		
	f.close();
}


        
